home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
17 Bit Software 3: The Continuation
/
17-Bit_The_Continuation_Disc.iso
/
amigan
/
amigan 5
/
secmap
/
secmap.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-01-27
|
12KB
|
344 lines
/* :ts=8 bk=0
* Disk mapper. Uses trackdisk.device to grab and read sector bitmap
* to discover what's allocated, then displays a (hopefully) pretty picture
* showing disk useage.
*
* Crufted together by Leo Schwab while desperately bored. 8606.8
* Turned into something working for the Manx compiler. 8607.23
*/
#include <exec/types.h>
#include <exec/memory.h>
#include <intuition/intuition.h>
#include <libraries/dos.h>
#include <devices/trackdisk.h>
#define REV 0L
#define BLOCKSIZE TD_SECTOR
#define NUMBLOCKS (NUMCYLS * NUMHEADS * NUMSECS)
#define ROOTBLOCK (NUMBLOCKS / 2)
#define BITMAPINDEX 79
#define NUMLONGS (NUMBLOCKS / 32)
#define XX 6L
#define YY 6L
#define XOFF 30L
#define YOFF 25L
#define BRKOVER 91L /* 11 * YY + YOFF */
#define SEP 6
extern void *OpenLibrary(), *OpenDevice(), *OpenWindow(), *AllocMem(),
*Lock(), *Info(), *CreatePort(), *CreateExtIO();
extern long TextLength();
struct NewWindow windef = {
0, 0, 640, 180,
-1, -1,
CLOSEWINDOW,
WINDOWDRAG | WINDOWDEPTH | WINDOWCLOSE | SMART_REFRESH | ACTIVATE,
NULL, NULL,
(UBYTE *) "Disk Allocation Map ",
NULL, NULL, 0, 0, 0, 0,
WBENCHSCREEN
};
struct IntuiText ok = {
AUTOFRONTPEN, AUTOBACKPEN,
AUTODRAWMODE, AUTOLEFTEDGE, AUTOTOPEDGE,
AUTOITEXTFONT,
(UBYTE *) "OK",
AUTONEXTTEXT
};
struct IntuiText errmsg = {
AUTOFRONTPEN, AUTOBACKPEN,
AUTODRAWMODE, AUTOLEFTEDGE, AUTOTOPEDGE,
AUTOITEXTFONT,
NULL, /* Gets filled in later */
AUTONEXTTEXT
};
struct Window *win;
struct RastPort *rp;
struct InfoData *id;
struct IOExtTD *diskreq;
struct MsgPort *diskport;
ULONG diskchangecount, lok, *diskbuffer;
void *IntuitionBase, *GfxBase;
main (ac, av)
char *av[];
{
long k, x, y;
int unit, bmsect, free = NUMBLOCKS-2;
short i, n, l;
char buf[80];
if (!ac) { /* Run from workbench (ick!) */
/* I'll make this part better someday..... */
strcpy (buf, "df0:");
} else { /* Run from CLI (thank you) */
if (ac == 1) {
printf ("Drive specifier: ");
gets (buf);
} else
strcpy (buf, av[1]);
}
openstuff ();
if (!(lok = Lock (buf, ACCESS_READ)))
die ("Can't obtain lock for specified device.");
if (!(id = AllocMem ((long) sizeof (*id), MEMF_CLEAR)))
die ("Can't get InfoData memory.");
if (!Info (lok, id))
die ("Call to Info() failed.");
if (id -> id_DiskType == ID_NO_DISK_PRESENT)
die ("No disk in drive.");
unit = id -> id_UnitNumber;
FreeMem (id, (long) sizeof (*id)); id = NULL;
opendisk (unit);
MotorOn ();
GetSector ((long) ROOTBLOCK);
bmsect = diskbuffer[BITMAPINDEX];
GetSector ((long) bmsect);
MotorOff ();
/*
* At this point, we now have the bitmap in the disk buffer.
* This is what the first longword in the bitmap represents:
*
* 333322222222221111111111
* 32109876543210987654321098765432 Sector #
* --------------------------------
* 10100101001010010010010001010011 Longword
* MSB LSB
*
* If the bit is set, the sector is free.
*
* Sectors 0 and 1 contain the boot block. Thus, the DOS is not
* allowed to walk on them, and they are permanently allocated.
* However, the bitmap does not reflect this i.e. the bitmap starts
* at sector 2, which is indicated by bit 0, longword 1. This means
* we have to offset everything by two. Can you say "crock?"
*
* Actually, I suppose this is good, since it prevents some would-be
* smart person from un-allocating those sectors and messing things
* up badly.
*
* Bitmap starts at longword 1; longword 0 appears to be some kind
* of significant garbage (checksum?)
*
* For more info on how I found the bitmap sector, consult the DOS
* Technical Reference Manual, p. 1-1 - 1-2
*/
SetAPen (rp, 3L);
RectFill (rp, XOFF, YOFF, XX+XOFF, YY+YY+YOFF); /* Show first two */
for (i=1; i<=NUMLONGS; i++) {
k = diskbuffer[i];
for (n=0; n<32; n++)
/* Bits progress from low to high order */
if (i<NUMLONGS || n<30) { /* Ignore last two */
if (~k & 1) {
/* Perform icky conversion */
free--;
l = (i-1 << 5) + n + 2;
x = (l / 22) * XX + XOFF;
y = (l % 22) * YY + YOFF;
if (y >= BRKOVER)
y += SEP;
RectFill (rp, x, y, x+XX-1, y+YY-1);
}
k >>= 1;
}
}
/* Draw grid so we can see */
SetAPen (rp, 1L);
for (x=XOFF; x<=80*XX+XOFF; x += XX) {
Move (rp, x, YOFF);
Draw (rp, x, YOFF+11*YY);
Move (rp, x, BRKOVER+SEP);
Draw (rp, x, BRKOVER+SEP+11*YY);
}
for (y=0; y<=11*YY; y += YY) {
Move (rp, XOFF, y+YOFF);
Draw (rp, XOFF+80*XX, y+YOFF);
Move (rp, XOFF, y+SEP+BRKOVER);
Draw (rp, XOFF+80*XX, y+SEP+BRKOVER);
}
/* Draw map markings */
Move (rp, XOFF+XX/2, YOFF); Draw (rp, XOFF+XX/2, YOFF-3);
Move (rp, XOFF+80*XX-XX/2, YOFF); Draw (rp, XOFF+80*XX-XX/2, YOFF-3);
Move (rp, XOFF, YOFF+YY/2); Draw (rp, XOFF-3, YOFF+YY/2);
Move (rp, XOFF, YOFF+YY*10+YY/2); Draw (rp, XOFF-3, YOFF+YY*10+YY/2);
Move (rp, XOFF-1, YOFF-3); Text (rp, "0", 1L);
Move (rp, XOFF+79*XX-1, YOFF-3); Text (rp, "79", 2L);
Move (rp, XOFF-12, YOFF+6); Text (rp, "0", 1L);
Move (rp, XOFF-20, YOFF+11*YY); Text (rp, "10", 2L);
/* Do labels */
sprintf (buf, "Bitmap on sector %d", bmsect);
Move (rp, XOFF, 176L);
Text (rp, buf, (long) strlen (buf));
sprintf (buf, "Sectors free: %d", free);
Move (rp, 250L, 176L);
Text (rp, buf, (long) strlen (buf));
sprintf (buf, "Allocated: %d", (int) NUMBLOCKS-free);
Move (rp, 450L, 176L);
Text (rp, buf, (long) strlen (buf));
Move (rp, 520L, 60L);
Text (rp, "Surface 0", 9L);
Move (rp, 520L, 132L);
Text (rp, "Surface 1", 9L);
/* Wait for close gadget */
Wait (1L << win -> UserPort -> mp_SigBit);
closestuff ();
}
openstuff ()
{
if (!(IntuitionBase = OpenLibrary ("intuition.library", REV))) {
/*
* If we can't open Intuition, then we can't use
* AutoRequest ()
*/
printf ("Intuition failed; you'll have to use logic.\n");
closestuff ();
exit (100);
}
if (!(GfxBase = OpenLibrary ("graphics.library", REV))) {
printf ("Art shop closed.\n");
closestuff ();
exit (100);
}
if (!(win = OpenWindow (&windef))) {
printf ("Window painted shut.\n");
closestuff ();
exit (100);
}
rp = win -> RPort;
}
opendisk (unit)
int unit;
{
long err;
char *buf[80];
if (!(diskport = CreatePort (NULL, NULL)))
die ("No port.");
if (!(diskreq = CreateExtIO (diskport, (long) sizeof (*diskreq))))
die ("Can't make IO block.");
if (err = OpenDevice (TD_NAME, (long) unit, diskreq, NULL)) {
sprintf (buf, "Can't get at disk; err = %ld.", err);
DeleteExtIO (diskreq, (long) sizeof (*diskreq));
diskreq = NULL;
die (buf);
}
if (!(diskbuffer = AllocMem (BLOCKSIZE, MEMF_CLEAR | MEMF_CHIP)))
die ("Can't allocate disk buffer.");
diskreq -> iotd_Req.io_Command = TD_CHANGENUM;
DoIO (diskreq);
diskchangecount = diskreq -> iotd_Req.io_Actual;
}
closestuff ()
{
if (lok)
UnLock (lok);
if (diskreq) {
CloseDevice (diskreq);
DeleteExtIO (diskreq, (long) sizeof (*diskreq));
}
if (diskbuffer)
FreeMem (diskbuffer, (long) BLOCKSIZE);
if (id)
FreeMem (id, (long) sizeof (*id));
if (diskport)
DeletePort (diskport);
if (win)
CloseWindow (win);
if (GfxBase)
CloseLibrary (GfxBase);
if (IntuitionBase)
CloseLibrary (IntuitionBase);
}
die (str)
UBYTE *str;
{
errmsg.IText = str;
AutoRequest (win, &errmsg, NULL, &ok, NULL, NULL,
TextLength (rp, str, (long) strlen (str)) + 40, 46L);
closestuff ();
exit (100);
}
/*
* The following routines were stolen from an RKM example by Bob Peck and
* hacked up a bit.
*/
GetSector (sector)
long sector;
{
LONG offset = sector * BLOCKSIZE;
diskreq -> iotd_Req.io_Length = BLOCKSIZE;
diskreq -> iotd_Req.io_Data = (APTR) diskbuffer;
/* show where to put the data when read */
diskreq -> iotd_Req.io_Command = ETD_READ;
/* check that disk not changed before reading */
diskreq -> iotd_Count = diskchangecount;
/* convert from cylinder, head, sector to byte-offset value to get
* right one (as dos and everyone else sees it)...*/
/* driver reads one CYLINDER at a time (head does not move for
* 22 sequential sector reads, or better-put, head doesnt move for
* 2 sequential full track reads.)
*/
diskreq -> iotd_Req.io_Offset = offset;
DoIO (diskreq);
return (0);
}
MotorOn()
{
/* TURN ON DISK MOTOR ... old motor state is returned in io_Actual */
diskreq -> iotd_Req.io_Length = 1;
/* this says motor is to be turned on */
diskreq -> iotd_Req.io_Command = TD_MOTOR;
/* do something with the motor */
DoIO (diskreq);
return (0);
}
MotorOff()
{
diskreq -> iotd_Req.io_Length = 0;
/* says that motor is to be turned on */
diskreq -> iotd_Req.io_Command = TD_MOTOR;
/* do something with the motor */
DoIO (diskreq);
return (0);
}